﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CoreRay;
using CoreRay.Collections;

namespace CoreRay.Debugging
{
    /// <summary>
    /// Interaction logic for BinaryTreeVisualizerControl.xaml
    /// </summary>
    public partial class BinaryTreeVisualizerControl : UserControl
    {
        public BinaryTreeVisualizerControl()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(BinaryTreeVisualizerControl_Loaded);
        }

        void BinaryTreeVisualizerControl_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.BinaryTree != null)
            {
                // TODO: Make it work with all types of T
                BinaryTree<BvhTreeNodeData> test = (BinaryTree<BvhTreeNodeData>) this.BinaryTree;

                StackPanel stackPanel = new StackPanel();
                stackPanel.HorizontalAlignment = HorizontalAlignment.Center;
                stackPanel.Margin = new Thickness(5, 15, 5, 5);

                this.mainPanel.Children.Add(stackPanel);

                BindTreeNode(test.Root, stackPanel, 0, null);

                this.mainPanel.UpdateLayout();
                this.mainPanel.Width = 5000;
                this.mainPanel.Height = 2000;
                
                MakeConnections(stackPanel, null);
            }
        }

        public object BinaryTree { get; set; }

        private void BindTreeNode(BinaryTreeNode<BvhTreeNodeData> treeNode, StackPanel stackPanel, int currentLevel, Control parentControl)
        {
            // Add node data control
            Button button = new Button();
            button.Width = 300;
            button.Height = 70;
            button.Content = string.Format("Level: {0}\nTriangles Count: {1}\nBounding Box: {2}", currentLevel, treeNode.Data.TrianglesCount, treeNode.Data.BoundingBox);

            stackPanel.Children.Add(button);

            // Add stack panels
            StackPanel childrenStackPanel = new StackPanel();
            childrenStackPanel.HorizontalAlignment = HorizontalAlignment.Center;
            childrenStackPanel.Orientation = Orientation.Horizontal;
            childrenStackPanel.Margin = new Thickness(5);
            stackPanel.Children.Add(childrenStackPanel);

            StackPanel leftStackPanel = new StackPanel();
            leftStackPanel.HorizontalAlignment = HorizontalAlignment.Center;
            leftStackPanel.Margin = new Thickness(5, 15, 5, 5);
            childrenStackPanel.Children.Add(leftStackPanel);

            StackPanel rightStackPanel = new StackPanel();
            rightStackPanel.HorizontalAlignment = HorizontalAlignment.Center;
            rightStackPanel.Margin = new Thickness(5, 15, 5, 5);
            childrenStackPanel.Children.Add(rightStackPanel);

            // Process left child
            if (treeNode.LeftChild != null)
            {
                BindTreeNode(treeNode.LeftChild, leftStackPanel, currentLevel + 1, button);
            }

            // Process right child
            if (treeNode.RightChild != null)
            {
                BindTreeNode(treeNode.RightChild, rightStackPanel, currentLevel + 1, button);
            }
        }

        private void MakeConnections(Panel parentPanel, Control parentControl)
        {
            try
            {
                if (parentPanel != null)
                {
                    Control childControl = parentPanel.Children.OfType<Button>().FirstOrDefault();

                    if (parentControl != null)
                    {
                        Line line = new Line();

                        Point parentPosition = parentControl.TranslatePoint(new Point(150, 70), this.mainPanel);
                        Point childPosition = childControl.TranslatePoint(new Point(150, 0), this.mainPanel);

                        line.X1 = parentPosition.X;
                        line.Y1 = parentPosition.Y;
                        line.X2 = childPosition.X;
                        line.Y2 = childPosition.Y;
                        line.Stroke = new SolidColorBrush(System.Windows.Media.Colors.Black);

                        this.mainPanel.Children.Add(line);
                    }

                    if (parentPanel.Children.Count > 0)
                    {
                        var rootStackPanel = parentPanel.Children.OfType<StackPanel>().FirstOrDefault();

                        if (rootStackPanel != null)
                        {
                            foreach (Panel panel in rootStackPanel.Children.OfType<StackPanel>())
                            {
                                MakeConnections(panel, childControl);
                            } 
                        }
                    }      
                }
            }
            catch { }
        }
    }
}
